package com.xzzz.irda.guardcat.server.repos.mysql;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xzzz.common.base.util.BeanUtil;
import com.xzzz.common.base.util.DateUtils;
import com.xzzz.irda.guardcat.server.app.pojo.MachineInfo;
import com.xzzz.irda.guardcat.server.metric.MetricRepository;
import com.xzzz.irda.guardcat.server.repos.mysql.mappers.GcMapper;
import com.xzzz.irda.guardcat.server.repos.mysql.pojo.GcMySQLEntity;
import com.xzzz.irda.guardcat.server.metric.gc.GcInfo;
import com.xzzz.irda.tracker.core.adapter.aspect.TrackerStart;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author xzzz
 */
@Slf4j
public class GcRepositoryInMySQL extends MetricRepository<GcInfo> {

    public static final String PS_SCAVENGE = "PS Scavenge";
    public static final String PS_MARKSWEEP = "PS MarkSweep";

    @Autowired
    private GcMapper gcMapper;

    @Override
    public void save(MachineInfo machineInfo, GcInfo gcInfo) {
        QueryWrapper<GcMySQLEntity> where = new QueryWrapper<>();
        where.eq("machine_id", machineInfo.getMachineId()).eq("gc_id", gcInfo.getGcId());
        boolean exists = gcMapper.exists(where);
        if (exists) {
            return;
        }

        GcMySQLEntity entity = toEntity(gcInfo);
        entity.setAppName(machineInfo.getAppName());
        entity.setMachineId(machineInfo.getMachineId());
        gcMapper.insert(entity);
    }

    @Override
    @TrackerStart
    @Scheduled(cron = "0 0/1 * * * ?")
    public void expire() {
        long start = System.currentTimeMillis();
        Date today = DateUtil.date();
        // 删除2天前的
        Date expireDate = DateUtil.offsetDay(today, -1);
        String expireDateStr = DateUtil.format(expireDate, "yyyy-MM-dd HH:mm:ss");

        QueryWrapper<GcMySQLEntity> query = new QueryWrapper<>();
        query.le("cre_time", expireDate);
        int num = gcMapper.delete(query);
        log.info("[GUARDCAT] 删除小于 [{}] GC   信息, 共:[{}], 用时: {}", expireDateStr, num, System.currentTimeMillis() - start);
    }

    @Override
    public GcInfo getByMachineId(String machineId) {
        QueryWrapper<GcMySQLEntity> where = new QueryWrapper<>();
        where.eq("machine_id", machineId)
                .orderByDesc("cre_time")
                .last("limit 1");
        return entityTo(gcMapper.selectOne(where));
    }

    /**
     * @param machineId 机器的 id
     * @return
     */
    @Override
    public List<GcInfo> listByMachineId(String machineId) {
        QueryWrapper<GcMySQLEntity> where = new QueryWrapper<>();
        where.eq("machine_id", machineId)
                .orderByDesc("cre_time")
        ;

        List<GcMySQLEntity> entities = gcMapper.selectList(where);
        if (CollUtil.isEmpty(entities)) {
            return new ArrayList<>();
        }

        List<GcInfo> gcs = new ArrayList<>();
        for (GcMySQLEntity entity : entities) {
            gcs.add(entityTo(entity));
        }
        return gcs;
    }

    @Override
    public List<GcInfo> list(MachineInfo machineInfo, GcInfo gcInfo, Map<String, Object> args) {
        LambdaQueryWrapper<GcMySQLEntity> gcWhere = new LambdaQueryWrapper<GcMySQLEntity>()
                .eq(GcMySQLEntity::getMachineId, machineInfo.getMachineId())
                .eq(GcMySQLEntity::getName, gcInfo.getName())
                .orderByDesc(GcMySQLEntity::getCreTime)
                .last(args.get("last").toString());

        return BeanUtil.toList(gcMapper.selectList(gcWhere), GcInfo.class);
    }

    public GcInfo entityTo(GcMySQLEntity entity) {
        GcInfo gc = BeanUtil.toObj(entity, GcInfo.class);
        gc.setCreTime(DateUtils.toYMDHMS(entity.getCreTime()));
        return gc;
    }

    public GcMySQLEntity toEntity(GcInfo gcInfo) {
        GcMySQLEntity entity = BeanUtil.toObj(gcInfo, GcMySQLEntity.class);
        entity.setCreTime(DateUtils.parse(gcInfo.getCreTime()));
        return entity;
    }
}
